package com.bh.构建者模式.builder1;



/**
 * 当一个类的构造函数参数超过4个，
 * 而且这些参数有些是可选的时，我们通常有两种办法来构建它的对象。
 * 例如我们现在有如下一个类计算机类Computer，其中cpu与ram是必填参数，
 * 而其他3个是可选参数，那么我们如何构造这个类的实例呢,通常有两种常用的方式:
 * 第一：折叠构造函数模式（telescoping constructor pattern ）
 * 第二种：Javabean 模式(get/set)
 *
 * 第一种主要是使用及阅读不方便。你可以想象一下，当你要调用一个类的构造函数时，你首先要决定使用哪一个，然后里面又是一堆参数，如果这些参数的类型很多又都一样，你还要搞清楚这些参数的含义，很容易就传混了。。。那酸爽谁用谁知道。
 * 第二种方式在构建过程中对象的状态容易发生变化，造成错误。因为那个类中的属性是分步设置的，所以就容易出错。
 * 为了解决这两个痛点，builder模式就横空出世了。
 *
 * 可以看到，文章最开始的使用方式是传统builder模式的变种， 首先其省略了director 这个角色，将构建算法交给了client端，其次将builder 写到了要构建的产品类里面，最后采用了链式调用。
 */
public class Computer {
    private final String cpu;//必须
    private final String ram;//必须
    private final int usbCount;//可选
    private final String keyboard;//可选
    private final String display;//可选

    private Computer(Builder builder){
        this.cpu=builder.cpu;
        this.ram=builder.ram;
        this.usbCount=builder.usbCount;
        this.keyboard=builder.keyboard;
        this.display=builder.display;
    }
    public static class Builder{
        private String cpu;//必须
        private String ram;//必须
        private int usbCount;//可选
        private String keyboard;//可选
        private String display;//可选

        //下面的this指代的是谁调用Builder this指代的就是谁，这里的this 是指new Computer这个对象
        public Builder(String cup,String ram){
            this.cpu=cup;
            this.ram=ram;
        }

        public Builder setUsbCount(int usbCount) {
            this.usbCount = usbCount;
            return this;
        }
        public Builder setKeyboard(String keyboard) {
            this.keyboard = keyboard;
            return this;
        }
        public Builder setDisplay(String display) {
            this.display = display;
            return this;
        }
        //返回构建好的对象
        public Computer build(){
            return new Computer(this);
        }
    }
    //省略getter方法
}